/***************************************************************************************
 * Copyright 2020 Infineon Technologies AG ( www.infineon.com ).                       *
 * All rights reserved.                                                                *
 *                                                                                     *
 * Licensed  Material-Property of Infineon Technologies AG.                            *
 * This software is made available solely pursuant to the terms of Infineon            *
 * Technologies AG agreement which governs its use. This code and the information      *
 * contained in it are proprietary and confidential to Infineon Technologies AG.       *
 * No person is allowed to copy, reprint, reproduce or publish any part of this code,  *
 * nor disclose its contents to others, nor make any use of it, nor allow or assist    *
 * others to make any use of it - unless by prior Written express authorization of     *
 * Infineon Technologies AG and then only to the extent authorized.                    *
 *                                                                                     *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,            *
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,           *
 * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED.  IN NO       *
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     *
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,                 *
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;         *
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY             *
 * WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR            *
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF              *
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                                          *
 *                                                                                     *
 ***************************************************************************************/
/**
 * @file   i2c_bus_command.c
 * @date   June, 2020
 * @brief  Implementation of i2c bus commands
 */


#include "ecc.h"
#include "helper.h"
#include "auths_api.h"
#include "auths_status.h"
#include "auths_config.h"

#include "i2c_bus.h"
#include "i2c_bus_command.h"

extern AuthS_Capability auths_capability;


/**
* @brief Generates I2C BRES command
* @param device_address device I2C address
*/
uint16_t i2c_bus_command_BRES(uint8_t device_address)
{
	IIC_Struct s_I2C_inst;
	uint8_t cnt = 0;
	uint16_t uw_crc;
	uint16_t ret = INF_I2C_INIT;

	s_I2C_inst.AddrOfSlave = device_address;
	s_I2C_inst.BufferPtr[cnt++]= BRES;
	// CRC
	uw_crc = crc16_gen(s_I2C_inst.BufferPtr,cnt);
	s_I2C_inst.BufferPtr[cnt++]= LoByte(uw_crc);
	s_I2C_inst.BufferPtr[cnt++]= HiByte(uw_crc);
	s_I2C_inst.SendByteCnt = cnt;

	ret = I2C_SendOnly(&s_I2C_inst);

	delay_ms(1);
	return ret;
}

/**
* @brief Generates I2C PDWN command
* @param device_address Device I2C Address
*/
uint16_t i2c_bus_command_PDWN(uint8_t device_address)
{
	IIC_Struct s_I2C_inst;
	uint8_t cnt = 0;
	uint16_t uw_crc;
	uint16_t ret = INF_I2C_INIT;

	s_I2C_inst.AddrOfSlave = device_address;
	s_I2C_inst.BufferPtr[cnt++]= PDWN;

	// CRC
	uw_crc = crc16_gen(s_I2C_inst.BufferPtr,cnt);
	s_I2C_inst.BufferPtr[cnt++]= LoByte(uw_crc);
	s_I2C_inst.BufferPtr[cnt++]= HiByte(uw_crc);
	s_I2C_inst.SendByteCnt = cnt;

	ret = I2C_SendOnly(&s_I2C_inst);
	delay_ms(10);

	return ret;
}

/**
* @brief Generates I2C WD command
* @param device_address Device I2C Address
* @param uwAddr Write address
* @param data_len Data length to write
* @param ub_data Data to be written
*/
uint16_t i2c_bus_command_WD(uint8_t device_address, uint16_t uwAddr, uint8_t data_len, uint8_t *ub_data)
{
	IIC_Struct s_I2C_inst;
	uint8_t cnt = 0;
	uint16_t uw_crc;
	//uint16_t ret = INF_I2C_INIT;

#if (HOST_AUTHENTICATION_FEATURE_SUPPORTED==1)
	if(auths_capability.host_auth_done==host_auth_not_done){
		return SDK_E_HOST_AUTH;
	}
#endif
	s_I2C_inst.AddrOfSlave = device_address;
	s_I2C_inst.BufferPtr[cnt++]= WD;
	s_I2C_inst.BufferPtr[cnt++]= HiByte(uwAddr);
	s_I2C_inst.BufferPtr[cnt++]= LoByte(uwAddr);
	s_I2C_inst.BufferPtr[cnt++]= data_len;
	memcpy(s_I2C_inst.BufferPtr+cnt, ub_data, data_len);
	cnt += data_len;

	// CRC
	uw_crc = crc16_gen(s_I2C_inst.BufferPtr,cnt);
	s_I2C_inst.BufferPtr[cnt++]= LoByte(uw_crc);
	s_I2C_inst.BufferPtr[cnt++]= HiByte(uw_crc);
	s_I2C_inst.SendByteCnt = cnt;

	return I2C_SendOnly(&s_I2C_inst);
}

/**
* @brief Generates I2C RD command
* @param device_address Device I2C Address
* @param uwAddr Read address
* @param rd_len Data length to read
* @param ub_data Data to be read
*/
uint16_t i2c_bus_command_RD(uint8_t device_address, uint16_t uwAddr, uint8_t rd_len, uint8_t *ub_data)
{
	IIC_Struct s_I2C_inst;
	uint8_t cnt = 0;
	uint16_t uw_crc;
	uint16_t ret = INF_I2C_INIT;

	s_I2C_inst.AddrOfSlave = device_address;
	s_I2C_inst.BufferPtr[cnt++]= RD;
	s_I2C_inst.BufferPtr[cnt++]= HiByte(uwAddr);
	s_I2C_inst.BufferPtr[cnt++]= LoByte(uwAddr);
	s_I2C_inst.BufferPtr[cnt++]= rd_len;

	// CRC
	uw_crc = crc16_gen(s_I2C_inst.BufferPtr, cnt);
	s_I2C_inst.BufferPtr[cnt++]= LoByte(uw_crc);
	s_I2C_inst.BufferPtr[cnt++]= HiByte(uw_crc);	
	s_I2C_inst.SendByteCnt = cnt;
	s_I2C_inst.RecvByteCnt = rd_len+CRC_BYTE_LEN;

	ret = I2C_SendAndReceive(&s_I2C_inst);
	if(ret != INF_I2C_SUCCESS){
		ret = INF_I2C_E_READ;
		return ret;
	}

	memcpy(ub_data, s_I2C_inst.BufferPtr, rd_len);
	return INF_I2C_SUCCESS;
}

/**
* @brief Generates I2C WDA command
* @param device_address Device I2C Address
* @param ubAddr Device address to be changed
*/
uint16_t i2c_bus_command_WDA(uint8_t device_address, uint16_t ubAddr)
{
    IIC_Struct s_I2C_inst;
	uint8_t cnt = 0;
	uint16_t uw_crc;
	uint16_t ret = INF_I2C_INIT;

#if (HOST_AUTHENTICATION_FEATURE_SUPPORTED==1)
	   if(auths_capability.host_auth_done==host_auth_not_done){
		return SDK_E_HOST_AUTH;
	}
#endif
	s_I2C_inst.AddrOfSlave = device_address;
	s_I2C_inst.BufferPtr[cnt++]= WDA;
	s_I2C_inst.BufferPtr[cnt++]= ubAddr;
	
	// CRC
	uw_crc = crc16_gen(s_I2C_inst.BufferPtr, cnt);
	s_I2C_inst.BufferPtr[cnt++]= LoByte(uw_crc);
	s_I2C_inst.BufferPtr[cnt++]= HiByte(uw_crc);
	s_I2C_inst.SendByteCnt = cnt;

	ret = I2C_SendOnly(&s_I2C_inst);
	if(INF_I2C_SUCCESS!=ret){
		ret = INF_I2C_E_WDA;
	}
	delay_ms(15);
	return ret;
}

/**
* @brief For Host Support Only: Value request
* @param device_address I2C device address
* @param ub_data data to be sent
*/
uint16_t i2c_bus_command_AVREQ(uint8_t device_address, uint8_t *ub_data)
{
    IIC_Struct s_I2C_inst;
	uint8_t cnt = 0;
	uint16_t uw_crc;
	//uint16_t ret = INF_I2C_INIT;

	s_I2C_inst.AddrOfSlave = device_address;
	s_I2C_inst.BufferPtr[cnt++]= AVREQ;
	memcpy(s_I2C_inst.BufferPtr+cnt, ub_data, MAC_BYTE_LEN);
	cnt += MAC_BYTE_LEN;
	// CRC
	uw_crc = crc16_gen(s_I2C_inst.BufferPtr,cnt);
	s_I2C_inst.BufferPtr[cnt++]= LoByte(uw_crc);
	s_I2C_inst.BufferPtr[cnt++]= HiByte(uw_crc);
	s_I2C_inst.SendByteCnt = cnt;

	return I2C_SendOnly(&s_I2C_inst);
}

/**
* @brief For Host Support Only: Value Request 1
* @param device_address I2C device address
* @param ub_data data to be sent
*/
uint16_t i2c_bus_command_AREQ1(uint8_t device_address, uint8_t *ub_data)
{
    IIC_Struct s_I2C_inst;
	uint8_t cnt = 0;
	uint16_t uw_crc;
	//uint16_t ret = INF_I2C_INIT;

	s_I2C_inst.AddrOfSlave = device_address;
	s_I2C_inst.BufferPtr[cnt++]= AREQ1;
	memcpy(s_I2C_inst.BufferPtr+cnt, ub_data,MAC_BYTE_LEN);
	cnt += MAC_BYTE_LEN;
	// CRC
	uw_crc = crc16_gen(s_I2C_inst.BufferPtr,cnt);
	s_I2C_inst.BufferPtr[cnt++]= LoByte(uw_crc);
	s_I2C_inst.BufferPtr[cnt++]= HiByte(uw_crc);
	s_I2C_inst.SendByteCnt = cnt;

	return I2C_SendOnly(&s_I2C_inst);
}

/**
* @brief For Host Support Only: Reponse 1
* @param device_address I2C device address
* @param ub_data data to be sent
*/
uint16_t i2c_bus_command_ARES1(uint8_t device_address, uint8_t *ub_data)
{
    IIC_Struct s_I2C_inst;
	uint8_t cnt = 0;
	uint16_t uw_crc;
	uint16_t ret = INF_I2C_INIT;

	s_I2C_inst.AddrOfSlave = device_address;
	s_I2C_inst.BufferPtr[cnt++]= ARES1;

	// CRC
	uw_crc = crc16_gen(s_I2C_inst.BufferPtr,cnt);
	s_I2C_inst.BufferPtr[cnt++]= LoByte(uw_crc);
	s_I2C_inst.BufferPtr[cnt++]= HiByte(uw_crc);
	s_I2C_inst.SendByteCnt = cnt;
	s_I2C_inst.RecvByteCnt = MAC_BYTE_LEN+CRC_BYTE_LEN;

	ret = I2C_SendAndReceive(&s_I2C_inst);
	if(ret != INF_I2C_SUCCESS)
	{
		ret = INF_I2C_E_READ;
		return ret;
	}

	memcpy(ub_data, s_I2C_inst.BufferPtr,MAC_BYTE_LEN);
	return INF_I2C_SUCCESS;
}

/**
* @brief Send ECCS1 command. Command is enabled only after host authentication operation
* @param device_address I2C device address
*/
uint16_t i2c_bus_command_ECCS1(uint8_t device_address)
{
    IIC_Struct s_I2C_inst;
	uint8_t cnt = 0;
	uint16_t uw_crc;
	//uint16_t ret = INF_I2C_INIT;

#if (HOST_AUTHENTICATION_FEATURE_SUPPORTED==1)	
	if(auths_capability.host_auth_done==host_auth_not_done){
		return SDK_E_HOST_AUTH;
	}
#endif

	s_I2C_inst.AddrOfSlave = device_address;
	s_I2C_inst.BufferPtr[cnt++]= ECCS1;
	// CRC
	uw_crc = crc16_gen(s_I2C_inst.BufferPtr,cnt);
	s_I2C_inst.BufferPtr[cnt++]= LoByte(uw_crc);
	s_I2C_inst.BufferPtr[cnt++]= HiByte(uw_crc);
	s_I2C_inst.SendByteCnt = cnt;

	return I2C_SendOnly(&s_I2C_inst);
}

/**
* @brief Send ECCSs command. Command is enabled only after host authentication operation
* @param device_address I2C device address
*/
uint16_t i2c_bus_command_ECCS2 (uint8_t device_address)
{
    IIC_Struct s_I2C_inst;
	uint8_t cnt = 0;
	uint16_t uw_crc;
	//uint16_t ret = INF_I2C_INIT;
	
#if (HOST_AUTHENTICATION_FEATURE_SUPPORTED==1)	
	if(auths_capability.host_auth_done==host_auth_not_done){
		return SDK_E_HOST_AUTH;
	}
#endif

	s_I2C_inst.AddrOfSlave = device_address;
	s_I2C_inst.BufferPtr[cnt++]= ECCS2;
	// CRC
	uw_crc = crc16_gen(s_I2C_inst.BufferPtr,cnt);
	s_I2C_inst.BufferPtr[cnt++]= LoByte(uw_crc);
	s_I2C_inst.BufferPtr[cnt++]= HiByte(uw_crc);
	s_I2C_inst.SendByteCnt = cnt;

	return I2C_SendOnly(&s_I2C_inst);
}

/**
* @brief Send ECCC command. Command is enabled only after host authentication operation
* @param device_address I2C device address
* @param ub_data data to be sent
*/
uint16_t i2c_bus_command_ECCC(uint8_t device_address, uint8_t *ub_data)
{
    IIC_Struct s_I2C_inst;
	uint8_t cnt = 0;
	uint16_t uw_crc;
	//uint16_t ret = INF_I2C_INIT;

#if (HOST_AUTHENTICATION_FEATURE_SUPPORTED==1)
	if(auths_capability.host_auth_done==host_auth_not_done){
		return SDK_E_HOST_AUTH;
	}
#endif

	s_I2C_inst.AddrOfSlave = device_address;
	s_I2C_inst.BufferPtr[cnt++]= ECCC;
	memcpy(s_I2C_inst.BufferPtr+cnt, ub_data, ECC_CHALLENGE_LEN);
	cnt += ECC_CHALLENGE_LEN;
	// CRC
	uw_crc = crc16_gen(s_I2C_inst.BufferPtr,cnt);
	s_I2C_inst.BufferPtr[cnt++]= LoByte(uw_crc);
	s_I2C_inst.BufferPtr[cnt++]= HiByte(uw_crc);
	s_I2C_inst.SendByteCnt = cnt;

	return I2C_SendOnly(&s_I2C_inst);
}

/**
* @brief Send ECCR command. Command is enabled only after host authentication operation
* @param device_address I2C device address
* @param ub_data data to be sent
*/
uint16_t i2c_bus_command_ECCR(uint8_t device_address, uint8_t *ub_data)
{
    IIC_Struct s_I2C_inst;
	uint8_t cnt = 0;
	uint16_t uw_crc;
	uint16_t ret = INF_I2C_INIT;

#if (HOST_AUTHENTICATION_FEATURE_SUPPORTED==1)
	if(auths_capability.host_auth_done==host_auth_not_done){
		return SDK_E_HOST_AUTH;
	}
#endif	

	s_I2C_inst.AddrOfSlave = device_address;
	s_I2C_inst.BufferPtr[cnt++]= ECCR;
	// CRC
	uw_crc = crc16_gen(s_I2C_inst.BufferPtr,cnt);
	s_I2C_inst.BufferPtr[cnt++]= LoByte(uw_crc);
	s_I2C_inst.BufferPtr[cnt++]= HiByte(uw_crc);
	s_I2C_inst.SendByteCnt = cnt;
	s_I2C_inst.RecvByteCnt = ECC_RESPONSE_LEN+CRC_BYTE_LEN;

	ret = I2C_SendAndReceive(&s_I2C_inst);
	if(ret != INF_I2C_SUCCESS){
		return ret;
	}

	memcpy(ub_data, s_I2C_inst.BufferPtr,ECC_RESPONSE_LEN);
	return INF_I2C_SUCCESS;
}

/**
* @brief Send MACS command. Command is enabled only after host authentication operation
* @param device_address I2C device address
* @param uw_mac_addr data to be MAC
*/
uint16_t i2c_bus_command_MACS(uint8_t device_address, uint16_t uw_mac_addr)
{
    IIC_Struct s_I2C_inst;
	uint8_t cnt = 0;
	uint16_t uw_crc;
	//uint16_t ret = INF_I2C_INIT;

#if (HOST_AUTHENTICATION_FEATURE_SUPPORTED==1)
	if(auths_capability.host_auth_done==host_auth_not_done){
		return SDK_E_HOST_AUTH;
	}
#endif

	s_I2C_inst.AddrOfSlave = device_address;
	s_I2C_inst.BufferPtr[cnt++]= MACS;
	s_I2C_inst.BufferPtr[cnt++]= HiByte(uw_mac_addr);
	s_I2C_inst.BufferPtr[cnt++]= LoByte(uw_mac_addr);

	// CRC
	uw_crc = crc16_gen(s_I2C_inst.BufferPtr,cnt);
	s_I2C_inst.BufferPtr[cnt++]= LoByte(uw_crc);
	s_I2C_inst.BufferPtr[cnt++]= HiByte(uw_crc);
	s_I2C_inst.SendByteCnt = cnt;

	return I2C_SendOnly(&s_I2C_inst);
}

/**
* @brief Send MACR command. Command is enabled only after host authentication operation
* @param device_address I2C device address
* @param ub_data data to be sent
*/
uint16_t i2c_bus_command_MACR(uint8_t device_address, uint8_t* ub_data)
{
	IIC_Struct s_I2C_inst;
	uint8_t cnt = 0;
	uint16_t uw_crc;
	uint16_t ret = INF_I2C_INIT;

#if (HOST_AUTHENTICATION_FEATURE_SUPPORTED==1)	
	if(auths_capability.host_auth_done==host_auth_not_done){
		return SDK_E_HOST_AUTH;
	}
#endif

	s_I2C_inst.AddrOfSlave = device_address;
	s_I2C_inst.BufferPtr[cnt++]= MACR;

	// CRC
	uw_crc = crc16_gen(s_I2C_inst.BufferPtr,cnt);
	s_I2C_inst.BufferPtr[cnt++]= LoByte(uw_crc);
	s_I2C_inst.BufferPtr[cnt++]= HiByte(uw_crc);
	s_I2C_inst.SendByteCnt = cnt;
	s_I2C_inst.RecvByteCnt = MAC_BYTE_LEN+CRC_BYTE_LEN;

	ret = I2C_SendAndReceive(&s_I2C_inst);
	if(ret != INF_I2C_SUCCESS){
		return ret;
	}

	memcpy(ub_data, s_I2C_inst.BufferPtr, MAC_BYTE_LEN);
	return INF_I2C_SUCCESS;
}

/**
* @brief Send MACK command. Command is enabled only after host authentication operation
* @param device_address I2C device address
* @param ub_data data to be sent
*/
uint16_t i2c_bus_command_MACK(uint8_t device_address, uint8_t* ub_data)
{
    IIC_Struct s_I2C_inst;
	uint8_t cnt = 0;
	uint16_t uw_crc;
	uint16_t ret = INF_I2C_INIT;

#if (HOST_AUTHENTICATION_FEATURE_SUPPORTED==1)
	if(auths_capability.host_auth_done==host_auth_not_done){
		return SDK_E_HOST_AUTH;
	}
#endif

	s_I2C_inst.AddrOfSlave = device_address;
	s_I2C_inst.BufferPtr[cnt++]= MACK;
	memcpy(s_I2C_inst.BufferPtr+cnt, ub_data,MAC_BYTE_LEN);
	cnt += MAC_BYTE_LEN;

	// CRC
	uw_crc = crc16_gen(s_I2C_inst.BufferPtr,cnt);
	s_I2C_inst.BufferPtr[cnt++]= LoByte(uw_crc);
	s_I2C_inst.BufferPtr[cnt++]= HiByte(uw_crc);
	s_I2C_inst.SendByteCnt = cnt;

	ret = I2C_SendOnly(&s_I2C_inst);
	if(ret != INF_I2C_SUCCESS){
		return ret;
	}
	delay_ms(20);
	return ret;
}

/**
* @brief Send MACCR1 command. Command is enabled only after host authentication operation
* @param device_address I2C device address
* @param ub_data data to be sent
*/
uint16_t i2c_bus_command_MACCR1(uint8_t device_address, uint8_t* ub_data)
{
	IIC_Struct s_I2C_inst;
	uint8_t cnt = 0;
	uint16_t uw_crc;
	//uint16_t ret = INF_I2C_INIT;

#if (HOST_AUTHENTICATION_FEATURE_SUPPORTED==1)
	if(auths_capability.host_auth_done==host_auth_not_done){
		return SDK_E_HOST_AUTH;
	}
#endif

	s_I2C_inst.AddrOfSlave = device_address;
	s_I2C_inst.BufferPtr[cnt++]= MACCR1;
	memcpy(s_I2C_inst.BufferPtr+cnt, ub_data,MAC_BYTE_LEN);
	cnt += MAC_BYTE_LEN;
	// CRC
	uw_crc = crc16_gen(s_I2C_inst.BufferPtr,cnt);
	s_I2C_inst.BufferPtr[cnt++]= LoByte(uw_crc);
	s_I2C_inst.BufferPtr[cnt++]= HiByte(uw_crc);
	s_I2C_inst.SendByteCnt = cnt;

	return I2C_SendOnly(&s_I2C_inst);
}

/**
* @brief Send MACCR2 command. Command is enabled only after host authentication operation
* @param device_address I2C device address
* @param ub_data data to be sent
*/
uint16_t i2c_bus_command_MACCR2(uint8_t device_address, uint8_t* ub_data)
{
	IIC_Struct s_I2C_inst;
	uint8_t cnt = 0;
	uint16_t uw_crc;
	//uint16_t ret = INF_I2C_INIT;

#if (HOST_AUTHENTICATION_FEATURE_SUPPORTED==1)
	if(auths_capability.host_auth_done==host_auth_not_done){
		return SDK_E_HOST_AUTH;
	}
#endif

	s_I2C_inst.AddrOfSlave = device_address;
	s_I2C_inst.BufferPtr[cnt++]= MACCR2;
	memcpy(s_I2C_inst.BufferPtr+cnt, ub_data,MAC_BYTE_LEN);
	cnt += MAC_BYTE_LEN;

	// CRC
	uw_crc = crc16_gen(s_I2C_inst.BufferPtr,cnt);
	s_I2C_inst.BufferPtr[cnt++]= LoByte(uw_crc);
	s_I2C_inst.BufferPtr[cnt++]= HiByte(uw_crc);
	s_I2C_inst.SendByteCnt = cnt;

	return I2C_SendOnly(&s_I2C_inst);
}

/**
* @brief Send MACCR3 command. Command is enabled only after host authentication operation
* @param device_address I2C device address
* @param ub_data data to be sent
*/
uint16_t i2c_bus_command_MACCR3(uint8_t device_address, uint8_t* ub_data)
{
	IIC_Struct s_I2C_inst;
	uint8_t cnt = 0;
	uint16_t uw_crc;
	//uint16_t ret = INF_I2C_INIT;

	if(auths_capability.host_auth_done==host_auth_not_done){
		return SDK_E_HOST_AUTH;
	}

	s_I2C_inst.AddrOfSlave = device_address;
	s_I2C_inst.BufferPtr[cnt++]= MACCR3;
	memcpy(s_I2C_inst.BufferPtr+cnt, ub_data, MAC_BYTE_LEN);
	cnt += MAC_BYTE_LEN;

	// CRC
	uw_crc = crc16_gen(s_I2C_inst.BufferPtr,cnt);
	s_I2C_inst.BufferPtr[cnt++]= LoByte(uw_crc);
	s_I2C_inst.BufferPtr[cnt++]= HiByte(uw_crc);
	s_I2C_inst.SendByteCnt = cnt;

	return I2C_SendOnly(&s_I2C_inst);
}

/**
* @brief Send MACCR4 command. Command is enabled only after host authentication operation
* @param device_address I2C device address
* @param ub_data data to be sent
*/
uint16_t i2c_bus_command_MACCR4(uint8_t device_address, uint8_t* ub_data)
{
	IIC_Struct s_I2C_inst;
	uint8_t cnt = 0;
	uint16_t uw_crc;
	//uint16_t ret = INF_I2C_INIT;

#if (HOST_AUTHENTICATION_FEATURE_SUPPORTED==1)
	if(auths_capability.host_auth_done==host_auth_not_done){
		return SDK_E_HOST_AUTH;
	}
#endif

	s_I2C_inst.AddrOfSlave = device_address;
	s_I2C_inst.BufferPtr[cnt++]= MACCR4;
	memcpy(s_I2C_inst.BufferPtr+cnt, ub_data, MAC_BYTE_LEN);
	cnt += MAC_BYTE_LEN;

	// CRC
	uw_crc = crc16_gen(s_I2C_inst.BufferPtr,cnt);
	s_I2C_inst.BufferPtr[cnt++]= LoByte(uw_crc);
	s_I2C_inst.BufferPtr[cnt++]= HiByte(uw_crc);
	s_I2C_inst.SendByteCnt = cnt;

	return I2C_SendOnly(&s_I2C_inst);
}

/**
* @brief Send MACCR5 command. Command is enabled only after host authentication operation
* @param device_address I2C device address
* @param ub_data data to be sent
*/
uint16_t i2c_bus_command_MACCR5(uint8_t device_address, uint8_t* ub_data)
{
	IIC_Struct s_I2C_inst;
	uint8_t cnt = 0;
	uint16_t uw_crc;
	//uint16_t ret = INF_I2C_INIT;

#if (HOST_AUTHENTICATION_FEATURE_SUPPORTED==1)
	if(auths_capability.host_auth_done==host_auth_not_done){
		return SDK_E_HOST_AUTH;
	}
#endif

	s_I2C_inst.AddrOfSlave = device_address;
	s_I2C_inst.BufferPtr[cnt++]= MACCR5;
	memcpy(s_I2C_inst.BufferPtr+cnt, ub_data, MAC_BYTE_LEN);
	cnt += MAC_BYTE_LEN;
	// CRC
	uw_crc = crc16_gen(s_I2C_inst.BufferPtr,cnt);
	s_I2C_inst.BufferPtr[cnt++]= LoByte(uw_crc);
	s_I2C_inst.BufferPtr[cnt++]= HiByte(uw_crc);
	s_I2C_inst.SendByteCnt = cnt;

	return I2C_SendOnly(&s_I2C_inst);
}

/**
* @brief Send HRREQ command. Command is enabled only after host authentication operation
* @param device_address I2C device address
*/
uint16_t i2c_bus_command_HRREQ(uint8_t device_address)
{
    IIC_Struct s_I2C_inst;
	uint8_t cnt = 0;
	uint16_t uw_crc;
	uint16_t ret = INF_I2C_INIT;

	s_I2C_inst.AddrOfSlave = device_address;
	s_I2C_inst.BufferPtr[cnt++] = HRREQ;

	// CRC
	uw_crc = crc16_gen(s_I2C_inst.BufferPtr, cnt);
	s_I2C_inst.BufferPtr[cnt++] = LoByte(uw_crc);
	s_I2C_inst.BufferPtr[cnt++] = HiByte(uw_crc);
	s_I2C_inst.SendByteCnt = cnt;

	ret = I2C_SendOnly(&s_I2C_inst);
	if (ret != INF_I2C_SUCCESS) {
		return ret; 
	} else {
		return INF_I2C_SUCCESS;
	}
}

/**
* @brief Send HRRES command. Command is enabled only after host authentication operation
* @param device_address I2C device address
* @param ub_data data to be sent
*/
uint16_t i2c_bus_command_HRRES(uint8_t device_address, uint8_t *ub_data)
{
	IIC_Struct s_I2C_inst;
	uint8_t cnt = 0;
	uint16_t uw_crc;
	uint16_t ret = INF_I2C_INIT;

	s_I2C_inst.AddrOfSlave = device_address;
	s_I2C_inst.BufferPtr[cnt++]= HRRES;
	// CRC
	uw_crc = crc16_gen(s_I2C_inst.BufferPtr,cnt);
	s_I2C_inst.BufferPtr[cnt++]= LoByte(uw_crc);
	s_I2C_inst.BufferPtr[cnt++]= HiByte(uw_crc);
	s_I2C_inst.SendByteCnt = cnt;
	s_I2C_inst.RecvByteCnt = MAC_BYTE_LEN+CRC_BYTE_LEN;

	ret = I2C_SendAndReceive(&s_I2C_inst);
	if(ret != INF_I2C_SUCCESS){
		return ret;
	}
	
	memcpy(ub_data, s_I2C_inst.BufferPtr,MAC_BYTE_LEN);
	return INF_I2C_SUCCESS;
}

/**
* @brief Send DRRES command. Command is enabled only after host authentication operation
* @param device_address I2C device address
* @param ub_data data to be sent
*/
uint16_t i2c_bus_command_DRRES(uint8_t device_address, uint8_t *ub_data)
{
	IIC_Struct s_I2C_inst;
	uint8_t cnt = 0;
	uint16_t uw_crc;
	//uint16_t ret = INF_I2C_INIT;

	s_I2C_inst.AddrOfSlave = device_address;
	s_I2C_inst.BufferPtr[cnt++]= DRRES;
	memcpy(s_I2C_inst.BufferPtr+cnt, ub_data, MAC_BYTE_LEN);
	cnt += MAC_BYTE_LEN;
	// CRC
	uw_crc = crc16_gen(s_I2C_inst.BufferPtr, cnt);
	s_I2C_inst.BufferPtr[cnt++]= LoByte(uw_crc);
	s_I2C_inst.BufferPtr[cnt++]= HiByte(uw_crc);
	s_I2C_inst.SendByteCnt = cnt;

	return I2C_SendOnly(&s_I2C_inst);
}

/**
* @brief Send HREQ1 command. Command is enabled only after host authentication operation
* @param device_address I2C device address
* @param ub_data data to be sent
*/
uint16_t i2c_bus_command_HREQ1(uint8_t device_address, uint8_t *ub_data)
{
    IIC_Struct s_I2C_inst;
	uint8_t cnt = 0;
	uint16_t uw_crc;
	//uint16_t ret = INF_I2C_INIT;

	s_I2C_inst.AddrOfSlave = device_address;
	s_I2C_inst.BufferPtr[cnt++]= HREQ1;
	memcpy(s_I2C_inst.BufferPtr+cnt, ub_data, MAC_BYTE_LEN);
	cnt += MAC_BYTE_LEN;
	// CRC
	uw_crc = crc16_gen(s_I2C_inst.BufferPtr, cnt);
	s_I2C_inst.BufferPtr[cnt++]= LoByte(uw_crc);
	s_I2C_inst.BufferPtr[cnt++]= HiByte(uw_crc);
	s_I2C_inst.SendByteCnt = cnt;

	return I2C_SendOnly(&s_I2C_inst);
}

/**
* @brief Send DRES1 command. Command is enabled only after host authentication operation
* @param device_address I2C device address
* @param ub_data data to be sent
*/
uint16_t i2c_bus_command_DRES1(uint8_t device_address, uint8_t *ub_data)
{
    IIC_Struct s_I2C_inst;
	uint8_t cnt = 0;
	uint16_t uw_crc;
	uint16_t ret = INF_I2C_INIT;

	s_I2C_inst.AddrOfSlave = device_address;
	s_I2C_inst.BufferPtr[cnt++]= DRES1;
	// CRC
	uw_crc = crc16_gen(s_I2C_inst.BufferPtr, cnt);
	s_I2C_inst.BufferPtr[cnt++]= LoByte(uw_crc);
	s_I2C_inst.BufferPtr[cnt++]= HiByte(uw_crc);
	s_I2C_inst.SendByteCnt = cnt;
	s_I2C_inst.RecvByteCnt = MAC_BYTE_LEN+CRC_BYTE_LEN;

	ret = I2C_SendAndReceive(&s_I2C_inst);
	if(ret != INF_I2C_SUCCESS)
	{
		return ret;
	}

	memcpy(ub_data, s_I2C_inst.BufferPtr, MAC_BYTE_LEN);
	return INF_I2C_SUCCESS;
}

